在Github Action里构建大型Docker镜像

GitHub 提供了非常好用的 Action 功能,最常见的是可以在里面做一些 CI 工作,比如单元测试、Lint等。

在国内,受一堵墙的影响,不少开发事项需要特殊的技巧方能正常进行,以至于中国程序员人均拥有比外国程序员更好的网络基础知识。

这堵墙在 Docker 镜像构建方面影响尤其大,虽然通过配置代理可以解决,但如果我们想在构建里再装一些 Python 的包之类的行为,很困难。

如果能利用 Github Action 来进行 Docker 镜像的构建,将会极大提升便利性和幸福感。

在 Github Action 的 marketplace 里能找到一些相关的工具,同时也可以直接在 workflow.yaml 里写 docker build 。

在一般的小型镜像构建任务里,这样就足够了,例如:

name: Docker Image CI

on:
  push:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up QEMU
      uses: docker/setup-qemu-action@v3
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3
    - name: Login to Docker Hub
      uses: docker/login-action@v3
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}
    - name: Build and push
      uses: docker/build-push-action@v5
      with:
        push: true
        tags: ${{ env.docker_namespace }}/${{ env.image_name }}:${{ version }} # 注意替换,直接写死也行

这样就实现了当向 main 分支提交代码时,就在 Ubuntu 环境下进行 docker 构建和推送。

但现在随着大模型的兴起,一些 AI 应用开始变得流行,比如 AI 绘图使用的开源软件 Stable Diffusion ,如果想把 SD 放在 Docker 镜像里,那一堆庞大的 Python 依赖(pytorch、cuda等),会导致 Github Action 执行时报错,提示磁盘已用尽。

这个解决方法很简单,但也有极限,自测经验是 13GB 左右的镜像是可以构建成功的。只需要在开始执行 Docker 镜像构建前执行这一段脚本进行磁盘清理即可:

name: Docker Image CI

on:
  push:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Free Disk Space (Ubuntu) # 就是通过这一步进行释放空间
      uses: jlumbroso/free-disk-space@main
      with:
        # 这个可能会删除一些你实际需要的工具,所以建议还是 false 让它保留
        # 如果你打算尝试移除它,可以再腾出大约6GB的空间
        tool-cache: false

        # 如果有你需要使用的,将其设置为 false ,比如这里我们要构建Docker,Docker相关的工具是不能删的
        android: true
        dotnet: true
        haskell: true
        large-packages: true
        docker-images: false
        swap-storage: true
    - name: Set up QEMU
      uses: docker/setup-qemu-action@v3
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3
    - name: Login to Docker Hub
      uses: docker/login-action@v3
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}
    - name: Build and push
      uses: docker/build-push-action@v5
      with:
        push: true
        tags: ${{ env.docker_namespace }}/${{ env.image_name }}:${{ version }} # 注意替换,直接写死也行

具体案例可以参考 https://github.com/sky-admin/serverless-pod-a1111-upload ,这是一个允许 A1111/Stable-Diffusion-WebUI 在 RunPod 的 serverless 服务上运行模型执行AI绘图的镜像。未来也许会详细介绍如何在 Runpod 上部署 SD 绘图服务。

那如果想构建更大的镜像呢?就需要自行提供 Action 执行所在的 Runner 了,这个目前还没有尝试,但有基本的思路和方案,未来尝试后再来分享。